
/**
 * 
 * IPv4地址转换成整数
 * 
 * 题目描述

存在一种虚拟IPv4地址，由4小节组成，每节的范围为0~255，以#号间隔，虚拟IPv4地址可以转换为一个32位的整数，例如：

128#0#255#255，转换为32位整数的结果为2147549183（0x8000FFFF）
1#0#0#0，转换为32位整数的结果为16777216（0x01000000）
现以字符串形式给出一个虚拟IPv4地址，限制第1小节的范围为1~128，即每一节范围分别为(1~128)#(0~255)#(0~255)#(0~255)，要求每个IPv4地址只能对应到唯一的整数上。

如果是非法IPv4，返回invalid IP

输入描述
输入一行，虚拟IPv4地址格式字符串

输出描述
输出一行，按照要求输出整型或者特定字符

备注
输入不能确保是合法的IPv4地址，需要对非法IPv4（空串，含有IP地址中不存在的字符，非合法的#分十进制，十进制整数不在合法区间内）进行识别，返回特定错误

用例
输入	100#101#1#5
输出	1684340997
说明	无
输入	1#2#3
输出	invalid IP
说明	无

 */

import java.util.Scanner;

/**
  * 
  题目解析
本题主要注意异常情况的处理，有如下几种异常情况：

IPv4存在空串，比如1##3#4
IPv4存在非法字符，比如a#b#c#d
IPv4组成部分不足，比如1#2#3
IPv4组成部分的十进制整数，不再合法区间内，比如255#255#255#255
其中，对于存在非法字符的情况，可以转整型时抛出异常的捕获流程中处理。

2023.05.24

本题的Java语言需要注意，最后输出的数可能会超出int类型，因此需要使用Long.parseLong

2023.06.06

如果ip地址如下：

01#01#01#01

我理解应该也要算作非法，实际考试可以带上试试

  */
public class IPv4地址转换成整数 {
    public static void main(String[] args) {
        

        try{

            Scanner sc = new Scanner(System.in);
            System.out.println(solution(sc.nextLine()));


        }catch(Exception e){
            //e.printStackTrace();
            System.out.println("invalid IP");

        }
    }

    public static long solution(String s) throws Exception {
        String[] addrs = s.split("#");
 
        // ip不是由4个小节组成, 则抛出异常
        if (addrs.length != 4) throw new Exception();
 
        // 每小节的取值范围
        int[][] ranges = {{1, 128}, {0, 255}, {0, 255}, {0, 255}};
 
        // 记录结果十六进制串
        StringBuilder hex = new StringBuilder();
 
        for (int i = 0; i < 4; i++) {
            // 如果这一小节转整型失败（包括空串, 非数字串等情况），则抛出异常
            int num = Integer.parseInt(addrs[i]);
 
            // 非0的但是含有前导0，则抛出异常（实际考试可以去掉这个校验试试）
            if (num != 0 && addrs[i].startsWith("0")) {
                throw new Exception();
            }
 
            // 不在指定范围内, 则抛出异常
            if (num < ranges[i][0] || num > ranges[i][1]) {
                throw new Exception();
            }
 
            // 将十进制数 num 转为十六进制串, 如果十六进制串不足2位, 则补足前导0
            hex.append(String.format("%2s", Integer.toHexString(num)).replace(" ", "0"));
        }
 
        return Long.parseLong(hex.toString(), 16);
    }

}
